#include <QDebug>
#include <QLabel>
#include <string>

#include <thread>

#include "widget.h"
#include "ui_widget.h"

#include "net/HttpManager.h"
#include "net/NetworkManager.h"

#include "encrypt/aes/qaesencryption.h"
#include "TLog.h"
#include "qqrencode.h"
#include "app-msg/AppMsg.h"
#include "zlib/ZipWrapper.h"
#include "qxt/gui/qxtglobalshortcut.h"
#include "tasync/TTaskQueue.h"


void appMsgTest()
{
    AppMsg::get().start();
}

void sqlite3Test()
{
    // TODO常见数据库的加密和解密和获取内容
}

void zlibTest()
{
    ZipWrapper zip;
    zip.UnzipFile("/Users/sl/Downloads/9f52e4830.zip","/Users/sl/");    // 同步解压

    // TODO压缩
}

void qrTest(QLabel *label)
{
    // 生成二维码
    QQREncode encoder;
    encoder.encode(QString("Nice to Meet You!"));
    QImage code = encoder.toQImage();

    label->setPixmap(QPixmap::fromImage(code.scaled(200,200)));

    // TODO二维码解码
}

void pingTest()
{
    // ping数据,支持循环ping，这个用来不想自己单独的设置ping服务器，又想测试当前网络是否通畅的问题
    // win可利用原生的接口、linux的qt接口也是有效的，mac需要单独处理
    NetworkManager *mgr = new NetworkManager({"223.5.5.5","114.114.114.114"});
    QObject::connect(mgr,&NetworkManager::onlineState,[](bool isOnline){
        qDebug() << isOnline;
    });
    mgr->start();
}

void httpTest()
{
    // 同步获取http数据
    QString result = HttpManager::accessResult("http://www.baidu.com",QHash<QString,QString>(),GET);
    qDebug() << result.size();
}

void TLogTest()
{
    try {
        // test文件日志,中文路径
#ifdef WIN32
        TLog::addLog("test",QString("D:/好的/test.txt").toStdString());
#endif

#ifdef __APPLE__
        TLog::addLog("test",QString("/Users/sl/好的/test.txt").toStdString());
#endif

#ifdef __linux__
        TLog::addLog("test",QString("/home/sl/好的/test.txt").toStdString());
#endif
        // 指定日志id写入
        TLogTrace("test",std::string("hello i'm test log"));
        TLogDebug("test",std::string("hello i'm test log"));
        TLogInfo("test",std::string("hello i'm test log"));
        TLogWarn("test",std::string("hello i'm test log"));
        TLogError("test",std::string("hello i'm test log"));
        TLogCritical("test",std::string("hello i'm test log"));
        TLog::flushLog("test");

        // 主日志
#ifdef WIN32
        TLog::addLog(TLOG_MAIN,"D:/abc.txt");
#endif

#ifdef __APPLE__
        TLog::addLog(TLOG_MAIN,QString("/Users/sl/abc.txt").toStdString());
#endif

#ifdef __linux__
        TLog::addLog(TLOG_MAIN,QString("/home/sl/abc.txt").toStdString());
#endif

        // 通用测试
        TTrace("Faltle {0} {1} {2}","nci",'5',100);
        TDebug("Faltle {0} {1} {2}","nci",'5',100);
        TInfo("Faltle {0} {1} {2}","nci",'5',100);
        TWarn("Faltle {0} {1} {2}","nci",'5',100);
        TError("Faltle {0} {1} {2}","nci",'5',100);
        TCritical("Faltle {0} {1} {2}","nci",'5',100);

        // 普通信息
        TInfo("english");
        TInfo(QString(u8"中文").toLocal8Bit());
        //        TInfo(QString("美丽").toLocal8Bit()); // win disorderly code

        // 错误
        TError("Faltle {0} {1} {2}","nci",'5',100);

        // 数字8位定长
        TInfo("Easy padding in numbers like {:08d}", 12);

        // 进制显示
        TWarn("Support for int: {0:d};  hex: {0:x};  oct: {0:o}; bin: {0:b}", 42);

        // 带文件名、行号、函数名
        TTrace("Support for floats {:03.2f}", 1.23456);

        // 参数支持
        TDebug("Positional args are {1} {0}..", std::string("too"), "supported");

        // 自定义类型
        TDebug("type test {1} {0}..", QString("QString"), "chars");

        // 显示为[left alig           ],中括号内位20个
        TCritical("{:<20}", "left alig");

        // 获取原生spdlog
        TLog::getLog(TLOG_MAIN)->getSpdLog()->info(std::string("spdlog test"));

        // 释放日志
        TLog::freeLog();
    } catch(const std::exception &ex) {
        qDebug() << ex.what();
    }
}

void aesTest()
{
    // AES初始化，PKCS7会在后面补充数据
    QAESEncryption encryption(QAESEncryption::AES_128, QAESEncryption::ECB, QAESEncryption::ZERO);

    QString key="33955195";
    QString data="BFEBFBFF000406F1Z9ABXEMP2345234sdfgsdfgsdfgerter";

    // 加密
    QByteArray hashKey = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Md5);
    QByteArray encodedText = encryption.encode(data.toUtf8(), hashKey);
    QString str_encode_text = encodedText.toBase64();

    // 解密
    qDebug()<<"encodedText:"<<str_encode_text;
    QByteArray decodedText = encryption.decode(QByteArray::fromBase64(str_encode_text.toUtf8()), hashKey);
    qDebug() << decodedText;
}

void hotKeyTest()
{
    /**
             * mac键      mac识别符   win识别符
             * shift      Shift
             * control    Meta
             * alt/option Alt
             * command    Ctrl
        */

    // 全局快捷键（即使处于后台仍然有效）
    QxtGlobalShortcut *m_short = new QxtGlobalShortcut;
    m_short->setShortcut(QKeySequence("Alt+A"));
    QObject::connect(m_short,&QxtGlobalShortcut::activated,[](){
        qDebug() << "active";
    });

    // if you want to modify hot key
    QKeySequence seq("Alt+B");
    m_short->setShortcut(seq);
}

void tasyncTest()
{
    // 单次定时器
    TTask time = std::bind([](){
        qDebug() << "single timeout" << QTime::currentTime();
    });
    qDebug() << "run:" << QTime::currentTime();
    TTaskQueue::get().queueTimerTask(time,1000,false);


    // 重复定时器测试
    TTask timeR = std::bind([](){
        qDebug() << "repeate timeout" << QTime::currentTime();
    });
    qDebug() << "run:" << QTime::currentTime();
    auto timer = TTaskQueue::get().queueTimerTask(timeR,5000,true);

    // 后台线程运行
    TTask task = std::bind([](){
        qDebug() << "background task" << 1 + 1;
    });
    TTaskQueue::get().queueBackgroundTask(task);
}

void Widget::guiTest()
{
    /* GUI更新测试：非UI线程，同步调用GUI更新任务，普通成员函数 */
    std::thread *t = new std::thread([this](){
        std::this_thread::sleep_for(std::chrono::seconds(3));
        TTask task = std::bind((void (Widget::*)(int, int))&Widget::resize,this,600,600);
        TTaskQueue::get().queueGuiTask(task,true);
    });
    t->detach();

    /* GUI更新测试：非UI线程，异步调用GUI更新任务，普通成员函数 */
    std::thread *tt = new std::thread([this](){
        std::this_thread::sleep_for(std::chrono::seconds(5));
        TTask task = std::bind((void (Widget::*)(int, int))&Widget::resize,this,200,200);
        TTaskQueue::get().queueGuiTask(task,true);
    });
    tt->detach();

    /* GUI线程调用：GUI线程禁止同步调用 */
    TTask asynctask = std::bind((void (Widget::*)(int, int))&Widget::resize,this,300,300);
    qDebug() << TTaskQueue::get().queueGuiTask(asynctask,false);

    /* GUI更新测试：绑定重载函数 */
    TTask task = std::bind((void (Widget::*)(int, int))&Widget::resize,this,200,200);
    TTaskQueue::get().queueGuiTask(task,false);
}

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    TLogTest();
    zlibTest();
    httpTest();
    aesTest();
    pingTest();
    qrTest(ui->label);
    hotKeyTest();
    appMsgTest();
    tasyncTest();
    guiTest();
}

Widget::~Widget()
{
    delete ui;
}

